package com.atguigu.gulimall.product.service.impl;

import com.alibaba.csp.sentinel.Entry;
import com.alibaba.csp.sentinel.SphU;
import com.alibaba.csp.sentinel.annotation.SentinelResource;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import com.alibaba.fastjson.TypeReference;
import com.atguigu.common.utils.PageUtils;
import com.atguigu.common.utils.Query;
import com.atguigu.common.utils.R;
import com.atguigu.gulimall.product.entity.SkuImagesEntity;
import com.atguigu.gulimall.product.entity.SpuInfoDescEntity;
import com.atguigu.gulimall.product.entity.SpuInfoEntity;
import com.atguigu.gulimall.product.feign.SeckillFeign;
import com.atguigu.gulimall.product.service.SkuImagesService;
import com.atguigu.gulimall.product.service.SkuSaleAttrValueService;
import com.atguigu.gulimall.product.service.SpuInfoDescService;
import com.atguigu.gulimall.product.vo.ItemSaleAttr;
import com.atguigu.gulimall.product.vo.ItemVo;
import com.atguigu.gulimall.product.vo.ProductGroup;
import com.atguigu.gulimall.product.vo.SeckillRedisVo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.ThreadPoolExecutor;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;

import com.atguigu.gulimall.product.dao.SkuInfoDao;
import com.atguigu.gulimall.product.entity.SkuInfoEntity;
import com.atguigu.gulimall.product.service.SkuInfoService;
import org.springframework.util.StringUtils;


@Service("skuInfoService")
@Slf4j
public class SkuInfoServiceImpl extends ServiceImpl<SkuInfoDao, SkuInfoEntity> implements SkuInfoService {
    @Autowired
    private SkuInfoService skuInfoService;
    @Autowired
    private SkuImagesService skuImagesService;
    @Autowired
    private SkuSaleAttrValueService skuSaleAttrValueService;
    @Autowired
    private SpuInfoDescService spuInfoDescService;
    @Autowired
    private AttrGroupServiceImpl attrGroupService;
    @Autowired
    private ThreadPoolExecutor threadPoolExecutor;
    @Autowired
    private SeckillFeign seckillFeign;
    @Override
    public PageUtils queryPage(Map<String, Object> params) {
        IPage<SkuInfoEntity> page = this.page(
                new Query<SkuInfoEntity>().getPage(params),
                new QueryWrapper<SkuInfoEntity>()
        );

        return new PageUtils(page);
    }

    @Override
    public PageUtils queryByCondition(Map<String, Object> params) {

        String min = (String) params.get("min");
        String max = (String) params.get("max");
        String key = (String) params.get("key");
        String brandId = (String) params.get("brandId");
        String catelogId = (String) params.get("catelogId");
        QueryWrapper<SkuInfoEntity> queryWrapper = new QueryWrapper<SkuInfoEntity>().ge("price",min);

        if(max!=null && !"0".equals(max)){
            queryWrapper.le("price",max);
        }
        if(brandId!=null && !"0".equals(brandId)){
            queryWrapper.eq("brand_id",brandId);
        }
        if(catelogId!=null && !"0".equals(catelogId)){
            queryWrapper.eq("catalog_id",catelogId);
        }
        if(!org.springframework.util.StringUtils.isEmpty(key)){
            queryWrapper.and(wrapper->{
                wrapper.eq("sku_id",key).or().like("sku_name",key);
            });
        }

        IPage<SkuInfoEntity> page = this.page(
                new Query<SkuInfoEntity>().getPage(params),
                queryWrapper
        );

        return new PageUtils(page);
    }

    public ItemVo itemResource1(Long skuId,BlockException exception)throws ExecutionException, InterruptedException{
        System.out.println("==============================");
        log.info("itemResource方法执行");
        return null;
    }

    @Override
    @SentinelResource(value = "itemResource",blockHandler = "itemResource1")
    public ItemVo item(Long skuId) throws ExecutionException, InterruptedException {

        ItemVo itemVo = new ItemVo();

        CompletableFuture<SkuInfoEntity> skuInfoCompletableFuture = CompletableFuture.supplyAsync(() -> {
            //保存sku基本信息
            SkuInfoEntity skuInfoEntity = skuInfoService.getById(skuId);
            itemVo.setInfo(skuInfoEntity);
            return skuInfoEntity;
        }, threadPoolExecutor);

        CompletableFuture<Void> attrsCompletableFuture = skuInfoCompletableFuture.thenAcceptAsync(skuInfoEntity -> {
            //保存属性信息
            List<ItemSaleAttr> itemSaleAttrs = skuSaleAttrValueService.getItemSaleAttrsWithSpuId(skuInfoEntity.getSpuId());
            itemVo.setItemAttrs(itemSaleAttrs);
        }, threadPoolExecutor);

        CompletableFuture<Void> descCompletableFuture = skuInfoCompletableFuture.thenAcceptAsync(skuInfoEntity -> {
            //保存商品详情
            SpuInfoDescEntity spuInfoDescEntity = spuInfoDescService.getById(skuInfoEntity.getSpuId());
            String[] split = spuInfoDescEntity.getDecript().split(",");
            spuInfoDescEntity.setDecript(split[0]);
            itemVo.setSpuInfoDescEntity(spuInfoDescEntity);
        }, threadPoolExecutor);

        CompletableFuture<Void> productGroupCompletableFuture = skuInfoCompletableFuture.thenAcceptAsync(skuInfoEntity -> {
            //保存规格参数
            List<ProductGroup> productGroups = attrGroupService.getProductGroups(skuInfoEntity.getSpuId(), skuInfoEntity.getCatalogId());
            itemVo.setProductGroups(productGroups);
        }, threadPoolExecutor);

        CompletableFuture<Void> imageCompletableFuture = CompletableFuture.runAsync(() -> {
            //保存图片信息
            List<SkuImagesEntity> skuImagesEntities = skuImagesService.list(new QueryWrapper<SkuImagesEntity>().eq("sku_id", skuId));
            itemVo.setSkuImagesEntities(skuImagesEntities);
        }, threadPoolExecutor);

        CompletableFuture<Void> seckillVoCompletableFuture = CompletableFuture.runAsync(() -> {
            //保存秒杀信息
            R r = null;
            try(Entry entry = SphU.entry("getSeckillWithSkuid")){
                r = seckillFeign.getSeckillWithSkuid(skuId);
            }catch (BlockException e){
                log.info("自定义资源限流");
            }

            if(r.getCode()==0){
                SeckillRedisVo data = r.getData("data", new TypeReference<SeckillRedisVo>() {});
                itemVo.setSeckillRedisVo(data);
                long currentTimeMillis = System.currentTimeMillis();
                if(data!=null && data.getEndTime()<currentTimeMillis){
                    itemVo.setSeckillRedisVo(null);
                }
            }
        }, threadPoolExecutor);


        CompletableFuture.allOf(attrsCompletableFuture,descCompletableFuture,productGroupCompletableFuture,imageCompletableFuture,seckillVoCompletableFuture).get();
        return itemVo;
    }

}